package com.mingle.iwalk;

import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.RemoteException;

public class TrackService extends Service {

	private final static String TAG = "TrackService";
	private final IBinder mBinder = new ServiceStub(this);
	private LocationManager mLocManager;
	private List<Location> mLocList = new ArrayList<Location>();
	
	private ITrackServiceListener mListener = null;
	
	public static final int TRACK_SERVICE_STATUS_IDLE = 0;
	public static final int TRACK_SERVICE_STATUS_GPS_DISABLE = 1;
	public static final int TRACK_SERVICE_STATUS_GPS_ENABLE = 2;
	public static final int TRACK_SERVICE_STATUS_LOCATING = 3;
	public static final int TRACK_SERVICE_STATUS_RUNNING = 4;
	
	public static final int TRACK_SERVICE_NOTIFY_LOC = 0;
	public static final int TRACK_SERVICE_NOTIFY_START = 1;
	public static final int TRACK_SERVICE_NOTIFY_STOP = 2;
	//public static final int TRACK_SERVICE_NOTIFY_POI = 3;
	public static final int TRACK_SERVICE_NOTIFY_ERROR = 4;
	
	private int mState = TRACK_SERVICE_STATUS_IDLE;
	private int mTrackingId = -1;
	private int mTrackingUUID = -1;
	private String mTrackPath;
	
	final int ADD_LOCATION = 0;
	final int ADD_POI = 1;
	final int STOP_SERVICE = 2;
	
	private Handler mHandler= new Handler()
	{
		@Override
        public void handleMessage(Message msg) {

            switch(msg.what) 
            {
            	case ADD_LOCATION:
            	{
            		Location loc = (Location) msg.obj;
            		mLocList.add(loc);
            		mState = TRACK_SERVICE_STATUS_RUNNING;	
            		
            		if(mListener != null)
            		{
            			try {
							mListener.onNotify(TRACK_SERVICE_NOTIFY_LOC, loc, TravelerInfo.INFO_INVALID_ID);
						} catch (RemoteException e) {
							
							e.printStackTrace();
						}
            		}
            	}
            	break;
            	
            	case STOP_SERVICE:
            	{
            		if(mLocList.size()!=0 && mTrackPath!=null && mTrackPath.length()!= 0)
            		{
            			Utils.createTrackFile(mTrackPath, mLocList);
            		}
            		
            		if(mListener != null)
            		{
            			try {
							mListener.onNotify(TRACK_SERVICE_NOTIFY_STOP, null, 0);
						} catch (RemoteException e) {
							
							e.printStackTrace();
						}
            		}
            		
            		//mTrackingId = TravelerInfo.INFO_INVALID_ID;
            		mListener = null;
            		//mState = TRACK_SERVICE_STATUS_IDLE;	 
            		
            		mLocList.clear();
            		
            	}
            	break;
            	
            	case ADD_POI:
            	{
            		Location loc = (Location) msg.obj;
            		if(loc != null)
            		{
            			mLocList.add(loc);
            		}
            		mState = TRACK_SERVICE_STATUS_RUNNING;	
            		
            		if(mListener != null)
            		{
            			try {
							mListener.onNotify(TRACK_SERVICE_NOTIFY_LOC, loc, msg.arg1);
						} catch (RemoteException e) {
							
							e.printStackTrace();
						}
            		}
            	}
            	break;
            }
            
		}

	};
	
	private void sendMessage(int type, Object obj, int extra)
	{
		Message m = mHandler.obtainMessage(type, extra, 0, obj);
		mHandler.sendMessage(m);
	}
	
	@Override
	public IBinder onBind(Intent i) {
		
		return mBinder;
	}

	@Override
	public void onCreate() {
		//Log.i(TAG, "onCreate");
		mState = TRACK_SERVICE_STATUS_IDLE;
		mLocList.clear();
		super.onCreate();
	}

	@Override
	public void onDestroy() {
		//Log.i(TAG, "onDestroy");
		mState = TRACK_SERVICE_STATUS_IDLE;
		if(mLocManager!=null)
		{
			mLocManager.removeUpdates(mPositionListener);
			mLocManager = null;
		}
		mLocList.clear();
		super.onDestroy();
	}
	
	public int startRecord(ITrackServiceListener listener)
	{
		//Log.i(TAG, "startRecord");

		mLocManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE); 
        mLocManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1000 * 50, 20, mPositionListener);
        
        mListener = listener;
        
        mState = TRACK_SERVICE_STATUS_LOCATING;	 
		return 0;
	}
	
	public int stopRecord()
	{
		//Log.i(TAG, "stopRecord");
		mLocManager.removeUpdates(mPositionListener);
		mLocManager = null;
		
		mTrackingId = TravelerInfo.INFO_INVALID_ID;
		mTrackingUUID = TravelerInfo.INFO_INVALID_ID;
		mState = TRACK_SERVICE_STATUS_IDLE;	 
		
		sendMessage(STOP_SERVICE, null, 0);
		
		return 0;
	}
	
	/*public void setServiceListener(ITrackServiceListener listener)
	{
		mListener = listener;
	}*/
	
	public int getTrackServiceState()
	{
		//Log.i(TAG, "getTrackServiceState");
		return mState;
	}
	
	public int getTrackId()
	{
		//Log.i(TAG, "getTrackServiceState");
		return mTrackingId;
	}
	
	public void setTrackId(int id)
	{
		mTrackingId = id;
	}
	
	public int getTrackUUID()
	{
		//Log.i(TAG, "getTrackServiceState");
		return mTrackingUUID;
	}
	
	public void setTrackUUID(int uuid)
	{
		mTrackingUUID = uuid;
	}
	
	public List<Location> getTrackList()
	{
		return mLocList;
	}
	
	public void setTrackPath(String path)
	{
		mTrackPath = path;
	}
	
	public List<Location> setTrackListener(ITrackServiceListener l)
	{
		mListener = l;
		
		return mLocList;
	}
	
	public void addPOI2Tracking(int id, Location loc)
	{
		sendMessage(ADD_POI, loc, id); 
	}
	
	public void addFakeLoc()
	{
		if(mState == TRACK_SERVICE_STATUS_IDLE)
		{
			return;
		}
		Location location = new Location(LocationManager.GPS_PROVIDER);
		location.setLatitude(30);
		location.setLongitude(104);
		location.setAltitude(500);
		location.setAccuracy(0);
		location.setTime(Calendar.getInstance().getTimeInMillis());
		sendMessage(ADD_LOCATION, location, TravelerInfo.INFO_INVALID_ID); 
	}
	
	
	static class ServiceStub extends ITrackService.Stub {
        WeakReference<TrackService> mService;
        
        ServiceStub(TrackService service) {
            mService = new WeakReference<TrackService>(service);
        }

		@Override
		public int startRecord(ITrackServiceListener listener) throws RemoteException {
			
			return mService.get().startRecord(listener);
		}

		@Override
		public int stopRecord() throws RemoteException {
			
			return mService.get().stopRecord();
		}

		@Override
		public int getTrackServiceState() throws RemoteException {
			
			return mService.get().getTrackServiceState();
		}

		@Override
		public void addFakeLoc() throws RemoteException {
			mService.get().addFakeLoc();
			
		}

		@Override
		public void setTrackId(int id) throws RemoteException {
			mService.get().setTrackId(id);

		}

		@Override
		public int getTrackId() throws RemoteException {
			return mService.get().getTrackId();
			
		}
		
		@Override
		public void setTrackUUID(int uuid) throws RemoteException {
			mService.get().setTrackUUID(uuid);
			
		}


		@Override
		public List<Location> getTrackList() throws RemoteException {
			return mService.get().getTrackList();
		}

		@Override
		public int getTrackUUID() throws RemoteException {
			return mService.get().getTrackUUID();
		}
		
		@Override
		public void setTrackPath(String path) throws RemoteException {
			mService.get().setTrackPath(path);
			
		}

		@Override
		public List<Location> setTrackListener(ITrackServiceListener l)
				throws RemoteException {
			return mService.get().setTrackListener(l);
			
		}

		@Override
		public void addPOI2Tracking(int id, Location loc) throws RemoteException {
			mService.get().addPOI2Tracking(id, loc);
			
		}
	}
	
	private  LocationListener mPositionListener = new  LocationListener()
    {

		@Override
		public void onLocationChanged(Location location) {
			
			sendMessage(ADD_LOCATION, location, 0); 
		}

		@Override
		public void onProviderDisabled(String provider) {
			mState = TRACK_SERVICE_STATUS_GPS_DISABLE;	 
	
		}

		@Override
		public void onProviderEnabled(String provider) {
			
			mState = TRACK_SERVICE_STATUS_GPS_ENABLE;	 
		}

		@Override
		public void onStatusChanged(String provider, int status, Bundle extras) {
			

		}
    	
    };
}
